interface ILogger {
	type: string
	info: any
	time: number
}

interface DBParams {
	name: string
	version: number
	objStore: { name: string; cursorIndexList?: { name: string; keyPath: string; unique: boolean }[] }
	parseLogger?: (log: any) => ILogger
}

class DB {
	name: string
	version: number
	objStore: { name: string; cursorIndexList?: { name: string; keyPath: string; unique: boolean }[] }
	parseLogger?: (log: any) => ILogger
	constructor(params: DBParams) {
		this.name = params.name //数据库名称
		this.version = params.version || 1 //数据库版本
		this.objStore = params.objStore
		this.parseLogger = params.parseLogger
	}

	/**
	 * @description 打开数据库
	 */
	openDB(): Promise<IDBDatabase> {
		return new Promise((resolve, reject) => {
			const request = window.indexedDB.open(this.name, this.version)
			request.onerror = (event) => {
				reject({ type: 'error', msg: '打开数据库失败' })
			}

			request.onsuccess = (event) => {
				const DB = request.result
				resolve(DB)
			}

			request.onupgradeneeded = (event) => {
				const DB = (event.target as IDBOpenDBRequest).result

				if (!DB.objectStoreNames.contains(this.objStore.name)) {
					const objectStore = DB.createObjectStore(this.objStore.name, { keyPath: 'id', autoIncrement: true })
					if (this.objStore.cursorIndexList) {
						for (const item of this.objStore.cursorIndexList) {
							objectStore.createIndex(item.name, item.keyPath, { unique: item.unique })
						}
					}
				}
				resolve(DB)
			}
		})
	}

	/**
	 * @description 仓库实例
	 * @param {*} writeable
	 */
	async transaction(writeable = false) {
		const mode = writeable ? 'readwrite' : 'readonly'
		try {
			const db = await this.openDB()
			return db.transaction([this.objStore.name], mode)
		} catch (e) {}
	}

	/**
	 * @description 增加数据
	 */
	async add(element: any) {
		try {
			const transaction = await this.transaction(true)
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				if (element instanceof Array) {
					element.forEach((item) => {
						let parseItem = this.parseLogger ? this.parseLogger(item) : item
						objectStore.add(parseItem)
					})
				} else {
					let parseItem = this.parseLogger ? this.parseLogger(element) : element
					objectStore.add(parseItem)
				}
			}
		} catch (e) {}
	}

	/**
	 * @description 获取全部数据
	 */
	async readAll(): Promise<ILogger[] | undefined> {
		try {
			const transaction = await this.transaction()
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				return new Promise((resolve, reject) => {
					const req = objectStore.getAll()
					req.onsuccess = (event) => {
						resolve(req.result)
					}
					req.onerror = (event) => {
						reject({ type: 'error', msg: '获取全部数据失败' })
					}
				})
			}
		} catch (e) {}
	}
	/**
	 * @description 获取全部数据
	 */
	async readAllByCursor(cursorKey?: IDBValidKey | IDBKeyRange, name?: string): Promise<ILogger[] | undefined> {
		try {
			const transaction = await this.transaction()
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				return new Promise((resolve, reject) => {
					const table = name ? objectStore.index(name) : objectStore
					const req = cursorKey ? table.openCursor(cursorKey) : table.openCursor()
					let result: ILogger[] = []
					req.onsuccess = (event) => {
						const cursor = req.result
						if (cursor) {
							result.push(cursor.value)
							cursor.continue()
						} else {
							resolve(result)
						}
					}
					req.onerror = (event) => {
						reject({ type: 'error', msg: '获取全部数据失败' })
					}
				})
			}
		} catch (e) {}
	}

	/**
	 * @description 获取某一个数据
	 */
	async getData(cursorKey: IDBValidKey | IDBKeyRange, name?: string) {
		try {
			const transaction = await this.transaction()
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				let val = name ? objectStore.index(name).get(cursorKey) : objectStore.get(cursorKey)
				return val.result
			}
		} catch (e) {}
	}

	/**
	 * @description 删除数据
	 */
	async delete(cursorKey: IDBValidKey | IDBKeyRange, name?: string) {
		try {
			const transaction = await this.transaction(true)
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				if (name) {
					const index = objectStore.index(name)
					if (index) {
						const req = index.openCursor(cursorKey)
						req.onsuccess = (event) => {
							const cursor = req.result
							if (cursor) {
								cursor.delete()
								cursor.continue()
							}
						}
					}
				} else {
					objectStore.delete(cursorKey)
				}
			}
		} catch (e) {}
	}
	/**
	 * @description 清空数据表
	 */
	async clear() {
		try {
			const transaction = await this.transaction(true)
			if (transaction) {
				const objectStore = transaction.objectStore(this.objStore.name)
				objectStore.clear()
			}
		} catch (e) {}
	}
}

const Logger = new DB({
	name: 'kdLogger',
	version: 1,
	objStore: {
		name: 'log',
		cursorIndexList: [
			{ name: 'time', keyPath: 'time', unique: false },
			{ name: 'type', keyPath: 'type', unique: false },
		],
	},
	parseLogger: (item: Omit<ILogger, 'time'>) => {
		return {
			...item,
			time: new Date().getTime(),
		}
	},
})
//日志保留时间 - 7天
try {
	let time = new Date().getTime() - 7 * 24 * 60 * 60 * 1000
	Logger.delete(IDBKeyRange.upperBound(time, true), 'time')
} catch (e) {}

export default Logger
